﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;

namespace Win.CSkin.Test
{
    public class Utils
    {
        /// <summary>
        /// 字符串转Unicode
        /// </summary>
        /// <param name="source">源字符串</param>
        /// <returns>Unicode编码后的字符串</returns>
        public static string String2Unicode(string source)
        {
            var bytes = Encoding.Unicode.GetBytes(source);
            var stringBuilder = new StringBuilder();
            for (var i = 0; i < bytes.Length; i += 2)
            {
                stringBuilder.AppendFormat("\\u{0:x2}{1:x2}", bytes[i + 1], bytes[i]);
            }
            return stringBuilder.ToString();
        }
        /// <summary>  
        /// 字符串转为UniCode码字符串  
        /// </summary>  
        /// <param name="s"></param>  
        /// <returns></returns>  
        public static string StringToUnicode(string s)
        {
            char[] charbuffers = s.ToCharArray();
            byte[] buffer;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < charbuffers.Length; i++)
            {
                buffer = System.Text.Encoding.Unicode.GetBytes(charbuffers[i].ToString());
                sb.Append(String.Format("\\u{0:X2}{1:X2}", buffer[1], buffer[0]));
            }
            return sb.ToString();
        }
        /// <summary>  
        /// Unicode字符串转为正常字符串  
        /// </summary>  
        /// <param name="srcText"></param>  
        /// <returns></returns>  
        public static string UnicodeToString(string srcText)
        {
            string dst = "";
            string src = srcText;
            int len = srcText.Length / 6;
            for (int i = 0; i <= len - 1; i++)
            {
                string str = "";
                str = src.Substring(0, 6).Substring(2);
                src = src.Substring(6);
                byte[] bytes = new byte[2];
                bytes[1] = byte.Parse(int.Parse(str.Substring(0, 2), System.Globalization.NumberStyles.HexNumber).ToString());
                bytes[0] = byte.Parse(int.Parse(str.Substring(2, 2), System.Globalization.NumberStyles.HexNumber).ToString());
                dst += Encoding.Unicode.GetString(bytes);
            }
            return dst;
        }

        public static string DecodeString(string unicode)
        {
            if (string.IsNullOrEmpty(unicode))
            {
                return string.Empty;
            }
            //string[] ls = unicode.Replace("\\", "").Split(new char[]{'u'},StringSplitOptions.RemoveEmptyEntries);
            string[] ls = unicode.Split(new string[] { "\\u" }, StringSplitOptions.RemoveEmptyEntries);
            StringBuilder builder = new StringBuilder();
            int len = ls.Length;
            for (int i = 0; i < len; i++)
            {
                //builder.Append((Char)ushort.Parse(ls[i], System.Globalization.NumberStyles.HexNumber));
                builder.Append(Convert.ToChar(ushort.Parse(ls[i], System.Globalization.NumberStyles.HexNumber)));

            }
            return builder.ToString();
        }

        /// <summary>
        /// Unicode解码
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string DeUnicode(string str)
        {
            //最直接的方法Regex.Unescape(str);
            Regex reg = new Regex(@"(?i)\\[uU]([0-9a-f]{4})");
            return reg.Replace(str, delegate (Match m) { return ((char)Convert.ToInt32(m.Groups[1].Value, 16)).ToString(); });
        }

        /// <summary>
        /// 获取本机IP
        /// </summary>
        /// <returns></returns>
        public static string getIP()
        {
            string name = System.Net.Dns.GetHostName();
            System.Net.IPAddress[] ipadrlist = System.Net.Dns.GetHostAddresses(name);
            foreach (System.Net.IPAddress ipa in ipadrlist)
            {
                if (ipa.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    return ipa.ToString();
            }

            return "";
        }

        public static List<ClassPropertyInfo> ForeachClassProperties<T>(T Model)
        {
            string str = string.Empty;
            List<ClassPropertyInfo> list = new List<ClassPropertyInfo>();
            try
            {
                foreach (PropertyInfo propertyInfo in Model.GetType().GetProperties())
                {
                    ClassPropertyInfo classPropertyInfo = new ClassPropertyInfo();
                    classPropertyInfo.PropertyName = propertyInfo.Name;
                    classPropertyInfo.PropertyValue = propertyInfo.GetValue((object)Model, (object[])null);
                    int num = !propertyInfo.PropertyType.IsGenericType ? 0 : (propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) ? 1 : 0);
                    classPropertyInfo.PropertyType = num == 0 ? propertyInfo.PropertyType : propertyInfo.PropertyType.GetGenericArguments()[0];
                    object[] customAttributes = propertyInfo.GetCustomAttributes(typeof(DescriptionAttribute), true);
                    if ((uint)customAttributes.Length > 0U)
                        classPropertyInfo.PropertyNameDescription = ((DescriptionAttribute)customAttributes[0]).Description;

                    object[] customSuggestAttributes = propertyInfo.GetCustomAttributes(typeof(SuggestAttribute), true);
                    if ((uint)customSuggestAttributes.Length > 0U)
                        classPropertyInfo.PropertyNameSuggest = ((SuggestAttribute)customSuggestAttributes[0]).Suggest;
                    list.Add(classPropertyInfo);
                }
            }
            catch (Exception ex)
            {
                str = ex.Message;
            }
            return list;
        }

        /// <summary>
        /// 打开一个遮罩层作为等待弹窗
        /// </summary>
        /// <param name="msg">显示的等待信息</param>
        /// <param name="owner">父页面</param>
        /// <param name="work">要处理的逻辑代码</param>
        /// <param name="workArg">逻辑代码参数</param>
        public static void ShowProcessing(string msg, Form owner, ParameterizedThreadStart work, object workArg = null)
        {
            FrmProcessing processingForm = new FrmProcessing(msg);
            dynamic expObj = new ExpandoObject();
            expObj.Form = processingForm;
            expObj.WorkArg = workArg;
            processingForm.SetWorkAction(work, expObj);
            processingForm.ShowDialog(owner);
            if (processingForm.WorkException != null)
            {
                throw processingForm.WorkException;
            }
        }

        public static string SerializeXml(object data)
        {
            using (StringWriter sw = new StringWriter())
            {
                XmlSerializer xz = new XmlSerializer(data.GetType());
                XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
                ns.Add("", "");
                xz.Serialize(sw, data, ns);
                return sw.ToString();
            }
        }

        /// <summary>
        /// 读取xml文件内容反序列化为指定Object
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="fileName">文件名称</param>
        /// <returns></returns>
        public static T XmlDeserializeByFile<T>(string fileName)
        {
            try
            {
                using (StreamReader sr = new StreamReader(fileName))
                {
                    XmlSerializer xmldes = new XmlSerializer(typeof(T));
                    object obj = xmldes.Deserialize(sr);

                    return (T)obj;
                }
            }
            catch (Exception e)
            {
                return default(T);
            }
        }

        /// <summary>
        /// xml字符串反序列化为指定Object
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xmlContent">xml字符串</param>
        /// <returns></returns>
        public static T XmlDeserialize<T>(string xmlContent)
        {
            try
            {
                //直接把xml字符串转为stream（不读文件），再反序列号
                var stream = new MemoryStream(Encoding.Default.GetBytes(xmlContent));

                XmlSerializer xmldes = new XmlSerializer(typeof(T));
                object obj = xmldes.Deserialize(stream);

                return (T)obj;
            }
            catch (Exception e)
            {
                return default(T);
            }
        }

        /// <summary>
        /// xml字符串反序列化为指定Object
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xmlContent">xml字符串</param>
        /// <returns></returns>
        public static T XmlDeserialize2<T>(string xmlContent)
        {
            try
            {
                using (StringReader sr = new StringReader(xmlContent))
                {
                    XmlSerializer xmldes = new XmlSerializer(typeof(T));
                    object obj = xmldes.Deserialize(sr);

                    return (T)obj;
                }
            }
            catch (Exception e)
            {
                return default(T);
            }
        }

    }

    /// <summary>
    /// 批处理
    /// </summary>
    public class CMDTools
    {
        #region 基础参数

        //异步执行信息
        private static string _strInfo = null;

        #endregion

        /// <summary>
        /// 运行cmd命令（会显示命令窗口）
        /// </summary>
        /// <param name="cmdExe">指定应用程序的完整路径(比如：D:\GetTopShelf.exe)</param>
        /// <param name="cmdStr">执行命令行参数（比如：ipconfig、ping、install 等命令）</param>
        /// <returns>返回结果内容</returns>
        public static string ShowRunCmdCommand(string cmdExe, string cmdStr)
        {
            string result = null;
            try
            {
                using (Process myPro = new Process())
                {
                    //指定启动进程是调用的应用程序和命令行参数
                    ProcessStartInfo psi = new ProcessStartInfo(cmdExe, cmdStr);
                    myPro.StartInfo = psi;
                    myPro.Start();
                    //myPro.WaitForExit();
                    myPro.Close();
                    result = $"执行：{cmdStr} 命令成功";
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return result;
        }

        /// <summary>
        /// 运行cmd命令（不显示命令窗口）
        /// </summary>
        /// <param name="cmdExe">指定应用程序的完整路径(比如：D:\GetTopShelf.exe)</param>
        /// <param name="cmdStr">执行命令行参数（比如：ipconfig、ping、install 等命令）</param>
        /// <returns>返回结果内容</returns>
        public static string HideRunCmdCommand(string cmdExe, string cmdStr)
        {
            string result = null;
            try
            {
                using (Process myPro = new Process())
                {
                    myPro.StartInfo.FileName = "cmd.exe";
                    myPro.StartInfo.UseShellExecute = false;
                    myPro.StartInfo.RedirectStandardInput = true;
                    myPro.StartInfo.RedirectStandardOutput = true;
                    myPro.StartInfo.RedirectStandardError = true;
                    myPro.StartInfo.CreateNoWindow = true;
                    myPro.Start();
                    //如果调用程序路径中有空格时，cmd命令执行失败，可以用双引号括起来 ，在这里两个引号表示一个引号（转义）
                    string str = string.Format(@"""{0}"" {1} {2}", cmdExe, cmdStr, "&exit");

                    myPro.StandardInput.WriteLine(str);
                    myPro.StandardInput.AutoFlush = true;
                    myPro.StandardInput.WriteLine("exit");
                    result = myPro.StandardOutput.ReadToEnd();
                    myPro.WaitForExit();
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return result;
        }

        /// <summary>
        /// 运行cmd命令（不显示命令窗口）
        /// </summary>
        /// <param name="cmdStr">执行命令（比如：ipconfig、ping、install 等命令）</param>
        /// <returns>返回结果内容</returns>
        public static string HideRunCmdCommand(string cmdStr)
        {
            string result = null;

            try
            {
                Process p = new Process();
                p.StartInfo.FileName = "cmd.exe";
                p.StartInfo.UseShellExecute = false;    //是否使用操作系统shell启动
                p.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息
                p.StartInfo.RedirectStandardOutput = true;//由调用程序获取输出信息
                p.StartInfo.RedirectStandardError = true;//重定向标准错误输出
                p.StartInfo.CreateNoWindow = true;//不显示程序窗口
                p.Start();//启动程序

                //向cmd窗口发送输入信息
                p.StandardInput.WriteLine(cmdStr + "&exit");

                p.StandardInput.AutoFlush = true;
                p.StandardInput.WriteLine("exit");
                //向标准输入写入要执行的命令。这里使用&是批处理命令的符号，表示前面一个命令不管是否执行成功都执行后面(exit)命令，如果不执行exit命令，后面调用ReadToEnd()方法会假死
                //同类的符号还有&&和||前者表示必须前一个命令执行成功才会执行后面的命令，后者表示必须前一个命令执行失败才会执行后面的命令

                //获取cmd窗口的输出信息
                result = p.StandardOutput.ReadToEnd();

                //StreamReader reader = p.StandardOutput;
                //string line=reader.ReadLine();
                //while (!reader.EndOfStream)
                //{
                //    str += line + "  ";
                //    line = reader.ReadLine();
                //}

                p.WaitForExit();//等待程序执行完退出进程
                p.Close();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

            return result;
        }

        /// <summary>
        /// 异步执行执行CMD命令
        /// </summary>
        /// <param name="cmdStr">执行命令参数（比如：ipconfig、ping、install 等命令）</param>
        public static void HideAsyncRunCmdCommand(string cmdStr)
        {
            _strInfo = null;
            try
            {
                Process p = new Process();
                p.StartInfo.FileName = "cmd";
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.RedirectStandardInput = true;
                p.StartInfo.RedirectStandardOutput = true;
                p.StartInfo.RedirectStandardError = true;
                p.StartInfo.CreateNoWindow = true;
                p.OutputDataReceived += new DataReceivedEventHandler(HideRunCmdCommand2_OutputDataReceived);
                p.Start();
                StreamWriter cmdWriter = p.StandardInput;
                p.BeginOutputReadLine();
                if (!String.IsNullOrEmpty(cmdStr))
                {
                    cmdWriter.WriteLine(cmdStr);
                }
                cmdWriter.Close();

                p.WaitForExit();
                p.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        //接收输出信息
        private static void HideRunCmdCommand2_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            _strInfo += e.Data + "\r\n";

        }

        //获取到异步执行CMD命令的信息
        public static string GetAsyncRunCmdCommandInfo()
        {
            return _strInfo;
        }

        /// <summary>
        /// 执行bat(批处理)文件
        /// </summary>
        /// <param name="filePathAndName">指定应用程序的完整路径(比如：D:\GetTopShelf.bat)</param>
        /// <param name="isShowCMDWindow">是否显示执行的命令行窗体(注意：false时是隐式执行，需要在bat文件中添加退出命令exit)</param>
        /// <returns>返回执行结果（true:表示成功）</returns>
        public static bool RunBatFile(string filePathAndName, bool isShowCMDWindow)
        {
            bool success = false;
            try
            {
                Process pro = new Process();
                FileInfo file = new FileInfo(filePathAndName);
                pro.StartInfo.WorkingDirectory = file.Directory.FullName;
                pro.StartInfo.FileName = filePathAndName;
                if (isShowCMDWindow)
                {
                    pro.StartInfo.UseShellExecute = true;
                    pro.StartInfo.CreateNoWindow = false;
                }
                else
                {
                    pro.StartInfo.UseShellExecute = false;
                    pro.StartInfo.CreateNoWindow = true;
                }

                pro.Start();
                //pro.WaitForExit();
                success = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Run Exception:" + ex.Message);
            }

            return success;
        }

    }//Class_end

}
